package org.vacoor.xqq.core.bean;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

/**
 * 唯一标识化且可被监听属性改变的数据
 * <p/>
 * 本来打算用 {@link java.util.Observable}, {@link java.util.Observer}, 但是有些需要获取变化前后的值
 *
 * @author: Vacoor
 */
public abstract class IdentifiableAndObservableData {
    private final Object lock = new Object();
    private PropertyChangeSupport changeSupport;
    private final long id;

    public IdentifiableAndObservableData(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    // ----------------
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        ensurePropertyChangeSupport();
        changeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propName, PropertyChangeListener listener) {
        ensurePropertyChangeSupport();
        changeSupport.addPropertyChangeListener(propName, listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        if (changeSupport == null) {
            return;
        }
        changeSupport.removePropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(String propName, PropertyChangeListener listener) {
        if (changeSupport == null) {
            return;
        }
        changeSupport.removePropertyChangeListener(propName, listener);
    }

    public PropertyChangeListener[] getPropertyChangeListeners() {
        PropertyChangeListener[] listeners = new PropertyChangeListener[0];
        if (changeSupport != null) {
            listeners = changeSupport.getPropertyChangeListeners();
        }
        return listeners;
    }

    public PropertyChangeListener[] getPropertyChangeListeners(String propName) {
        PropertyChangeListener[] listeners = new PropertyChangeListener[0];
        if (changeSupport != null) {
            listeners = changeSupport.getPropertyChangeListeners(propName);
        }
        return listeners;
    }

    public void firePropertyChange(String propName, Object oldValue, Object newValue) {
        if (changeSupport == null) {
            return;
        }
        changeSupport.firePropertyChange(propName, oldValue, newValue);
    }

    public void fireIndexedPropertyChange(String propName, int idx, Object oldValue, Object newValue) {
        if (changeSupport == null) {
            return;
        }
        changeSupport.fireIndexedPropertyChange(propName, idx, oldValue, newValue);
    }

    private void ensurePropertyChangeSupport() {
        if (changeSupport != null) {
            return;
        }
        synchronized (lock) {
            if (changeSupport == null) {
                changeSupport = new PropertyChangeSupport(this);
            }
        }
    }
}
